// components/chat/chat.ts
import api from '../../api/index'
import {createDialogueId, uuid} from '../../utils/util'
import {ChatItemType, ChatStatusEnum, TopicType, ChatReferenceType, GetChatReferenceDataType, MergeChatReferenceDataType} from "../../types/index";
import common from "../../common/index";
const app = getApp()
Component({

  /**
   * 组件的属性列表
   */
  properties: {

  },

  /**
   * 组件的初始数据
   */
  data: {
    uid: '',
    currentTopicId: '',
    currentTopicName: '',
    chatHistory: [],
    questionStr: '',
    conditionStatus: {
      r1: 1,
      aispire: 1,
      knowledge: 0,
      network: 0,
    },
    ChatStatusEnum,
    list: [],
    uploadedFiles: [] as Array<any>,
    showTemplateMenu: false,
    templatePlaceholderPosition: -1,
    keepCursorTimer: null as any,
    originalTemplateText: '',
    autoFocus: false,
    selectionStart: -1,
    selectionEnd: -1,
    fileIconMap: {
      pdf: '../../assets/image/pdf-icon.png',
      doc: '../../assets/image/word-icon.png',
      docx: '../../assets/image/word-icon.png',
      ppt: '../../assets/image/ppt-icon.png',
      pptx: '../../assets/image/ppt-icon.png',
      txt: '../../assets/image/txt-icon.png',
      md: '../../assets/image/txt-icon.png',
      markdown: '../../assets/image/txt-icon.png',
      xls: '../../assets/image/excel-icon.png',
      xlsx: '../../assets/image/excel-icon.png',
      csv: '../../assets/image/excel-icon.png',
      default: '../../assets/image/def-icon.png'
    }
  },
  lifetimes: {
    attached() {
      const user = common.getAppUserInfo()
      this.data.uid = user.uid
    },
    detached() {
      // 组件销毁时清除定时器
      if (this.data.keepCursorTimer) {
        clearInterval(this.data.keepCursorTimer)
        this.data.keepCursorTimer = null
      }
    }
  },

  /**
   * 组件的方法列表
   */
  methods: {
    handleChooseFile() {
      const maxFileCount = 5
      const currentCount = (this.data.uploadedFiles || []).length
      if (currentCount >= maxFileCount) {
        wx.showToast({
          title: '最多上传5个文件',
          icon: 'none'
        })
        return
      }
      const remaining = maxFileCount - currentCount
      wx.chooseMessageFile({
        count: remaining,
        type: 'file',
        extension: ['pdf', 'doc', 'docx', 'ppt', 'pptx', 'md', 'markdown', 'txt'],
        success: (res) => {
          const tempFiles = res.tempFiles || []
          if (!tempFiles.length) {
            return
          }
          const newFiles = tempFiles.map((file: any) => {
            const extension = this.extractFileExtension(file.name)
            const filePath = file.path || file.tempFilePath || ''
            return {
              name: file.name,
              size: file.size,
              sizeText: this.formatFileSize(file.size),
              path: filePath,
              extension: (extension || 'file').toUpperCase(),
              icon: this.getFileIcon(extension)
            }
          })
          this.setData({
            uploadedFiles: (this.data.uploadedFiles || []).concat(newFiles)
          })
        },
        fail: (err) => {
          console.error('选择文件失败:', err)
          wx.showToast({
            title: '未选择文件',
            icon: 'none'
          })
        }
      })
    },
    handleTemplateMenuToggle() {
      this.setData({
        showTemplateMenu: !this.data.showTemplateMenu
      })
    },
    handleTemplateSelect(e: BaseEvent) {
      const dataset = e.currentTarget.dataset
      const {type, year, limit} = dataset
      
      // 关闭菜单
      this.setData({
        showTemplateMenu: false
      })
      
      // 清除之前的定时器
      if (this.data.keepCursorTimer) {
        clearInterval(this.data.keepCursorTimer)
        this.data.keepCursorTimer = null
      }
      
      let questionText = ''
      let selectionStart = -1
      let selectionEnd = -1
      
      // 根据模板类型生成可编辑的问题模板
      if (type === 'keyword') {
        // 关键词模板
        questionText = `基于""，查找最近${year || 3}年引用数大于${limit || 100}的10个文献。`
        selectionStart = 3 // "基于"的长度
        selectionEnd = 3
      } else if (type === 'title') {
        // 标题模板
        questionText = '基于标题 ""，查找文献'
        selectionStart = 6 // 两个引号之间的位置
        selectionEnd = 6
      } else if (type === 'doi') {
        // DOI模板
        questionText = '基于DOI ""，查找文献'
        selectionStart = 7 // 两个引号之间的位置
        selectionEnd = 7
      }
      
      if (questionText) {
        // 保存占位符位置和原始模板文本
        this.data.templatePlaceholderPosition = selectionStart
        this.data.originalTemplateText = questionText
        
        // 先设置文本和光标位置
        this.setData({
          questionStr: questionText,
          selectionStart: selectionStart,
          selectionEnd: selectionEnd,
          autoFocus: true
        })
        
        // 延迟一点时间确保textarea已经更新并获得焦点
        setTimeout(() => {
          // 再次设置光标位置，确保定位准确
          this.setData({
            selectionStart: selectionStart,
            selectionEnd: selectionEnd
          })
          
          // 创建定时器，持续更新光标位置，确保光标在占位符位置闪烁
          this.data.keepCursorTimer = setInterval(() => {
            // 只有当文本内容还是模板文本时，才保持光标位置
            if (this.data.questionStr === this.data.originalTemplateText && this.data.templatePlaceholderPosition >= 0) {
              this.setData({
                selectionStart: this.data.templatePlaceholderPosition,
                selectionEnd: this.data.templatePlaceholderPosition
              })
            } else {
              // 文本已经改变，清除定时器
              if (this.data.keepCursorTimer) {
                clearInterval(this.data.keepCursorTimer)
                this.data.keepCursorTimer = null
              }
              this.data.templatePlaceholderPosition = -1
              this.data.originalTemplateText = ''
            }
          }, 100) // 每100ms更新一次光标位置
        }, 150)
      }
    },
    handleInputChange(e: any){
      const newValue = e.detail.value
      this.setData({
        questionStr: newValue
      })
      
      // 如果文本已经改变，清除保持光标的定时器
      if (this.data.keepCursorTimer && this.data.templatePlaceholderPosition >= 0) {
        if (newValue !== this.data.originalTemplateText) {
          clearInterval(this.data.keepCursorTimer)
          this.data.keepCursorTimer = null
          this.data.templatePlaceholderPosition = -1
          this.data.originalTemplateText = ''
        }
      }
    },
    handleInputFocus(e: any){
      // 如果存在模板占位符位置，且当前文本还是模板文本，将光标定位到占位符位置
      if (this.data.templatePlaceholderPosition >= 0 && this.data.questionStr === this.data.originalTemplateText) {
        setTimeout(() => {
          this.setData({
            selectionStart: this.data.templatePlaceholderPosition,
            selectionEnd: this.data.templatePlaceholderPosition
          })
        }, 50)
      }
    },
    handleRemoveFile(e: BaseEvent) {
      const { index } = e.currentTarget.dataset || {}
      const idx = Number(index)
      if (Number.isNaN(idx)) {
        return
      }
      const list = [...(this.data.uploadedFiles || [])]
      list.splice(idx, 1)
      this.setData({
        uploadedFiles: list
      })
    },
    extractFileExtension(filename: string = ''): string {
      const parts = filename.split('.')
      return parts.length > 1 ? (parts.pop() || '').toLowerCase() : ''
    },
    formatFileSize(size: number = 0): string {
      if (!size) {
        return ''
      }
      const kb = size / 1024
      if (kb < 1024) {
        return `${kb.toFixed(1)} KB`
      }
      const mb = kb / 1024
      return `${mb.toFixed(1)} MB`
    },
    getFileIcon(ext: string = ''): string {
      const lower = (ext || '').toLowerCase()
      const map = this.data.fileIconMap || {}
      return map[lower] || map.default || ''
    },
    changeConditionStatus(e: BaseEvent){
      const k: 'r1' | 'aispire' | 'knowledge' | 'network' = e.currentTarget.dataset.code
      if(this.data.conditionStatus[k]) {
        this.data.conditionStatus[k] = 0
      } else {
        this.data.conditionStatus[k] = 1
      }
      this.setData({
        [`conditionStatus.${k}`]: this.data.conditionStatus[k]
      })
    },
    async executeCreateTopic(topicName: string) {
      let res: TopicType = {
        topic_id: '',
        topic_name: '',
      }
      const uid = this.data.uid
      try {
        res = await api.createTopic({
          uid,
          search_text: topicName
        }) as TopicType
      } catch(e){
        console.log(e)
      }
      return res
    },
    executeChat(params: any, text: string, index: number){
      const chatItem: ChatItemType = this.data.chatHistory[index]
      const data = {
        uid: this.data.uid,
        topic_id: this.data.currentTopicId,
        search_text: text,
          ...params
      }
      api.chat('/aispire/chat', data, chatItem, {
        reasonCall: () => {
          wx.hideLoading()
          chatItem.reasoningObj = app.towxml(chatItem.reasoning, 'markdown', {
            theme: 'reason'
          });
          this.setData({
            [`chatHistory[${index}]`]: chatItem
          })
        },
        answerCall: () => {
          wx.hideLoading()
          chatItem.aispireObj = app.towxml(chatItem.aispire, 'markdown', {
            theme: 'answer'
          });
          this.setData({
            [`chatHistory[${index}]`]: chatItem
          })
        },
        completeCall: () => {
          this.setData({
            [`chatHistory[${index}]`]: chatItem
          })
          wx.hideLoading()
          this.triggerEvent('stop')
          
          // 在聊天完成后获取参考资料
          this.fetchChatReference(chatItem, index)
        }
      })
    },
    async executeAcademicSearch(text: string, index: number){
      const chatItem: ChatItemType = this.data.chatHistory[index]
      
      console.log('执行学术搜索，问题文本:', text)
      
      // 解析模板问题
      const isKeywordSearch = text.includes('基于"关键词') || (text.includes('基于"') && !text.includes('标题') && !text.includes('DOI号'))
      const isTitleSearch = text.includes('基于标题 "')
      const isDoiSearch = text.includes('基于DOI "')
      
      console.log('搜索类型 - 关键词:', isKeywordSearch, '标题:', isTitleSearch, 'DOI:', isDoiSearch)
      
      try {
        let result: any = null
        
        if (isKeywordSearch) {
          // 生成guid
          const guid = Math.random().toString(36).substring(2, 14)
          
          // 参考 keywordSearch 接口的请求参数格式
          const searchParams = {
            uid: this.data.uid,
            keywords: ["llm"], // 固定为 ["llm"]
            topic_id: this.data.currentTopicId,
            guid: guid,
            search_text: text
          }
          
          console.log('调用学术搜索接口（关键词）:', searchParams)
          result = await api.academicSearch(searchParams)
          console.log('学术搜索接口返回:', result)
        } else if (isTitleSearch || isDoiSearch) {
          // 提取搜索内容（去掉引号）
          const contentMatch = text.match(/基于标题\s*"(.+?)"/) || text.match(/基于DOI\s*"(.+?)"/)
          const searchContent = contentMatch ? contentMatch[1].trim() : ''
          
          // 生成清理后的搜索文本（去掉引号）
          let cleanSearchText = text
          if (isTitleSearch) {
            cleanSearchText = text.replace(/基于标题\s*"(.+?)"/, (match, p1) => `基于标题 ${p1.trim()} `)
          } else if (isDoiSearch) {
            cleanSearchText = text.replace(/基于DOI\s*"(.+?)"/, (match, p1) => `基于DOI ${p1.trim()} `)
          }
          
          // 调用精准检索接口 get_paper_info
          const guid = Math.random().toString(36).substring(2, 14)
          const payload: any = {
            uid: parseInt(this.data.uid) || this.data.uid, // 确保uid是数字类型
            topic_id: this.data.currentTopicId,
            guid,
            search_text: cleanSearchText,
            title: isTitleSearch ? cleanSearchText : undefined,
            doi: isDoiSearch ? searchContent : undefined
          }
          
          console.log('调用精准检索接口（get_paper_info）:', payload)
          result = await api.getPaperInfo(payload)
          console.log('精准检索接口返回:', result)
          
          // 将单条记录转换为列表结构，复用卡片渲染
          if (result && result.status === 'success' && result.data && !Array.isArray(result.data)) {
            const d = result.data
            const mapped = {
              title: d.title,
              abstract: d.abstract,
              year: d.year,
              authors: d.authors || [],
              journal: d.journal,
              url: d.url || d.pdf_url,
              citation_count: d.citationCount || d.citation_count || null
            }
            // 保持status字段，转换为数组格式
            result = { 
              status: 'success',
              data: [mapped] 
            }
          }
        }
        
        // 检查返回数据格式：status为success且data为数组
        if (result && result.status === 'success' && result.data && Array.isArray(result.data) && result.data.length > 0) {
          // 存储论文列表数据
          chatItem.paperList = result.data
          chatItem.isAcademicSearch = true
          
          // 学术搜索结果使用卡片展示，不生成markdown
          chatItem.aispire = ''
          chatItem.aispireObj = null
        } else if (result && result.status === 'fail') {
          chatItem.aispire = '未查询到相关文献'
          chatItem.aispireObj = app.towxml('未查询到相关文献', 'markdown', {
            theme: 'answer'
          });
        } else {
          chatItem.aispire = '未查询到相关文献'
          chatItem.aispireObj = app.towxml('未查询到相关文献', 'markdown', {
            theme: 'answer'
          });
        }
      } catch (error) {
        console.error('学术搜索失败:', error)
        chatItem.aispire = '搜索失败，请稍后重试'
        chatItem.aispireObj = app.towxml('搜索失败，请稍后重试', 'markdown', {
          theme: 'answer'
        });
      }
      
      chatItem.loading = false
      chatItem.finish = true
      chatItem.status = ChatStatusEnum.Stop
      
      this.setData({
        [`chatHistory[${index}]`]: chatItem
      })
      
      wx.hideLoading()
      this.triggerEvent('stop')
      
      // 学术搜索结果不需要获取参考资料，因为使用的是 academicSearch 接口
    },
    async sendQuestion() {
      const text = this.data.questionStr
      if (!text) {
        return
      }
      
      // 检查是否是模板问题（关键词/标题/DOI 三种模板）
      const isTemplateQuestion = (
        (text.includes('基于"') && text.includes('"')) ||
        text.includes('基于标题 "') ||
        text.includes('基于DOI "')
      )
      
      console.log('问题文本:', text)
      console.log('是否是模板问题:', isTemplateQuestion)
      
      wx.showLoading({
        title: '加载中',
        mask: true,
      })
      this.triggerEvent('start')
      const uid = this.data.uid
      const guid = uuid(12)
      const params = {
        guid,
        llm: 'deepseek-v3',
        files: [],
        knowledge_base: []
      }
      params.files = (this.data.uploadedFiles || [])
        .map((file: any) => ({
          name: file.name,
          path: file.path,
          size: file.size
        }))
      if (this.data.conditionStatus.r1) {
        params.llm = 'deepseek-r1'
      }
      if (this.data.conditionStatus.knowledge) {
        params.knowledge_base.push('private_knowledge_base')
      }
      if (this.data.conditionStatus.aispire) {
        params.knowledge_base.push('aispire_knowledge_base')
      }
      if (this.data.conditionStatus.network) {
        params.knowledge_base.push('online_search')
      }
      
      // 如果是模板问题，使用学术搜索接口
      if (isTemplateQuestion) {
        console.log('使用学术搜索接口')
        const errorMsg = await common.getCheckMsg(params)
        if (errorMsg) {
          wx.hideLoading()
          wx.showToast({
            title: errorMsg
          })
          this.triggerEvent('stop')
          return
        }
        if (!this.data.currentTopicId) {
          const topic = await this.executeCreateTopic(text)
          if (topic && topic.topic_id) {
            this.data.currentTopicId = topic.topic_id
            this.data.currentTopicName = topic.topic_name
          } else {
            wx.hideLoading()
            wx.showToast({
              title: '对话创建失败',
              icon: 'error'
            })
          }
        }
        wx.hideLoading()
        if (this.data.currentTopicId) {
          const dialogue_id = createDialogueId(`${uid}:${this.data.currentTopicId}:${text}:${guid}`, 12)
          const chatItem = common.getDefChatItem()
          chatItem.dialogue_id = dialogue_id
          chatItem.user = text
          chatItem.topicId = this.data.currentTopicId
          chatItem.status = ChatStatusEnum.Start
          this.data.chatHistory.unshift(chatItem)
          this.executeAcademicSearch(text, 0)
          this.setData({
            questionStr: '',
            chatHistory: this.data.chatHistory,
            uploadedFiles: []
          })
        } else {
          this.triggerEvent('stop')
        }
        return
      }
      
      // 普通聊天流程
      console.log('使用普通聊天接口')
      const errorMsg = await common.getCheckMsg(params)
      if (errorMsg) {
        wx.hideLoading()
        wx.showToast({
          title: errorMsg
        })
        this.triggerEvent('stop')
        return
      }
      if (!this.data.currentTopicId) {
        const topic = await this.executeCreateTopic(text)
        if (topic && topic.topic_id) {
          this.data.currentTopicId = topic.topic_id
          this.data.currentTopicName = topic.topic_name
        } else {
          wx.hideLoading()
          wx.showToast({
            title: '对话创建失败',
            icon: 'error'
          })
        }
      }
      wx.hideLoading()
      if (this.data.currentTopicId) {
        const dialogue_id = createDialogueId(`${uid}:${this.data.currentTopicId}:${text}:${guid}`, 12)
        const chatItem = common.getDefChatItem()
        chatItem.dialogue_id = dialogue_id
        chatItem.user = text
        chatItem.topicId = this.data.currentTopicId
        chatItem.status = ChatStatusEnum.Start
        this.data.chatHistory.unshift(chatItem)
        this.executeChat(params, text, 0)
        this.setData({
          questionStr: '',
          chatHistory: this.data.chatHistory,
          uploadedFiles: []
        })
      } else {
        this.triggerEvent('stop')
      }
    },
    async stopQuestion() {
      const chatItem: ChatItemType = this.data.chatHistory[0]
      chatItem.loading = false
      chatItem.finish = true
      chatItem.status = ChatStatusEnum.Stop
      this.setData({
        ['chatHistory[0]']: chatItem
      })
    },
    async enterTopic(topic: TopicType) {
      wx.showLoading({
        title: '加载中',
        mask: true
      })
      const {topic_id, topic_name} = topic
      this.data.currentTopicId = topic_id
      this.data.currentTopicName = topic_name
      this.data.chatHistory = []
      try {
        const res: any = await api.historyTopicDetail({
          uid: this.data.uid,
          topic_id: topic_id
        })
        if (res.chat_history && res.chat_history.length) {
          const list = res.chat_history.filter((item: any) => item.chat_type === 'llm')
          list.forEach((item: ChatItemType) => {
            item.reasoningFinish = true
            item.finish = true
            item.loading = false
            item.status = ChatStatusEnum.Stop
            item.similarQuestionList = []
            item.referenceList = []
            item.referenceListObj = {}
            item.userSelect = false
            item.answerSelect = false
            item.topicId = topic_id
            item.aispireObj = app.towxml(item.aispire, 'markdown', {
              theme: 'answer'
            });
            if(item.reference_list && item.reference_list.length) {
              item.referenceList = item.reference_list
              item.referenceList.forEach((rf) => {
                item.referenceListObj[`${rf.id}`] = rf
              })
            }
          })
          list.reverse()
          this.data.chatHistory = list
        }
      } catch(e){}
      this.setData({
        chatHistory: this.data.chatHistory,
        currentTopicName: this.data.currentTopicName
      }, () => {
        wx.pageScrollTo({
          selector: '.chat-comp >>> .bottomAnchor',
          duration: 300,
        })
      })
      wx.hideLoading()
    },
    /**
     * 进入新会话
     */
    enterNewTopic() {
      this.setData({
        questionStr: '',
        chatHistory: [],
        currentTopicName: '',
        currentTopicId: '',
      })
    },
    autoSendNewQuestion(condition: any, text: string){
      this.setData({
        questionStr: text,
        chatHistory: [],
        currentTopicName: '',
        currentTopicId: '',
        conditionStatus: condition,
      }, () => {
        this.sendQuestion()
      })
    },
    
    // 获取聊天参考资料
    async fetchChatReference(chatItem: ChatItemType, index: number) {
      try {
        console.log('=== 开始获取聊天参考资料 ===');
        console.log('对话ID:', chatItem.dialogue_id);
        console.log('话题ID:', this.data.currentTopicId);
        
        // 调用getChatReference接口获取参考资料
        const referenceData: GetChatReferenceDataType = {
          uid: this.data.uid,
          topic_id: this.data.currentTopicId,
          dialogue_id: chatItem.dialogue_id
        };
        
        const res = await api.getChatReference(referenceData);
        console.log('参考资料接口返回:', res);
        
        if (res && res.data && Array.isArray(res.data)) {
          const references: ChatReferenceType[] = res.data;
          console.log('获取到的参考资料:', references);
          
          // 更新聊天项中的参考资料
          chatItem.referenceList = references;
          chatItem.referenceListObj = {};
          
          // 构建参考资料对象映射
          references.forEach((ref) => {
            chatItem.referenceListObj[`${ref.id}`] = ref;
          });
          
          // 更新数据
          this.setData({
            [`chatHistory[${index}]`]: chatItem
          });
          
          // 调用mergeChatReference接口合并参考资料
          await this.mergeChatReference(chatItem, index);
        } else {
          console.log('没有获取到参考资料');
        }
      } catch (error) {
        console.error('获取聊天参考资料失败:', error);
      }
    },
    
    // 合并参考资料到聊天记录
    async mergeChatReference(chatItem: ChatItemType, index: number) {
      try {
        console.log('=== 开始合并参考资料 ===');
        
        // 根据接口要求，构建包含body字段的参数结构
        const mergeData = {
          uid: this.data.uid,
          topic_id: this.data.currentTopicId,
          dialogue_id: chatItem.dialogue_id,
          body: chatItem.aispire || '' // 使用AI回答的内容作为body
        };
        
        console.log('合并参考资料请求参数:', mergeData);
        
        const res = await api.mergeChatReference(mergeData);
        console.log('合并参考资料接口返回:', res);
        
        if (res && res.status === 'success') {
          console.log('参考资料合并成功');
        } else {
          console.log('参考资料合并失败:', res?.message || '未知错误');
        }
      } catch (error) {
        console.error('合并聊天参考资料失败:', error);
      }
    },
    
    // chat() {
    //   api.chat({
    //     uid: '290',
    //     topic_id: 'ce26d667645f59eb',
    //     search_text: '今天心情不好呀',
    //     guid: uuid(12),
    //     llm: 'deepseek-r1',
    //     files: [],
    //     knowledge_base: []
    //   }, (msg: any) => {
    //     if (msg) {
    //       if (Object.hasOwn(msg, 'reasoning')) {
    //         this.data.chatItem.reasoning += msg.reasoning
    //         this.data.chatItem.reasoningObj = app.towxml(this.data.chatItem.reasoning, 'markdown', {
    //           // theme:'dark',
    //           events:{
    //             tap: e => {
    //               console.log('tap',e);
    //             },
    //             change: e => {
    //               console.log('todo',e);
    //             }
    //           }
    //         });
    //         this.setData({
    //           ['chatItem.reasoningObj']: this.data.chatItem.reasoningObj
    //         })
    //       }
    //       if (Object.hasOwn(msg, 'answer')) {
    //         this.data.chatItem.aispire += msg.answer
    //         this.data.chatItem.aispireObj = app.towxml(this.data.chatItem.aispire, 'markdown', {
    //           // theme:'dark',
    //           events:{
    //             tap: e => {
    //               console.log('tap',e);
    //             },
    //             change: e => {
    //               console.log('todo',e);
    //             }
    //           }
    //         });
    //         this.setData({
    //           ['chatItem.aispireObj']: this.data.chatItem.aispireObj
    //         })
    //       }
    //     }
    //   })
    // },
  }
})
